package hc.server;

import hc.App;
import hc.JPTrayIcon;
import hc.core.ClientInitor;
import hc.core.ConditionWatcher;
import hc.core.ContextManager;
import hc.core.EventCenter;
import hc.core.IConstant;
import hc.core.IContext;
import hc.core.IEventHCListener;
import hc.core.IStatusListen;
import hc.core.IWatcher;
import hc.core.L;
import hc.core.Message;
import hc.core.MsgBuilder;
import hc.core.ReceiveServer;
import hc.core.RootConfig;
import hc.core.RootServerConnector;
import hc.core.data.DataClientAgent;
import hc.core.data.DataServerConfig;
import hc.core.data.ServerConfig;
import hc.core.sip.SIPManager;
import hc.core.util.CUtil;
import hc.core.util.HCURLUtil;
import hc.core.util.IHCURLAction;
import hc.core.util.IMsgNotifier;
import hc.core.util.LogManager;
import hc.core.util.StringUtil;
import hc.res.ImageSrc;
import hc.server.data.KeyComperPanel;
import hc.server.relay.RelayManager;
import hc.server.relay.RelayShutdownWatch;
import hc.server.ui.ClientDesc;
import hc.server.ui.JcipManager;
import hc.server.ui.LogViewer;
import hc.server.ui.ServerUIUtil;
import hc.server.ui.SingleMessageNotify;
import hc.server.ui.video.CapControlFrame;
import hc.server.ui.video.CapManager;
import hc.server.ui.video.CapPreviewPane;
import hc.server.ui.video.CapStream;
import hc.server.ui.video.CaptureConfig;
import hc.server.util.ServerCUtil;
import hc.util.BackServer;
import hc.util.ExitManager;
import hc.util.HttpUtil;
import hc.util.IBiz;
import hc.util.PropertiesManager;
import hc.util.ResourceUtil;
import hc.util.TokenManager;
import hc.util.UILang;

import java.awt.BorderLayout;
import java.awt.ComponentOrientation;
import java.awt.Desktop;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Insets;
import java.awt.SystemTray;
import java.awt.Toolkit;
import java.awt.TrayIcon.MessageType;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.font.TextAttribute;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Locale;
import java.util.Properties;

import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JPopupMenu;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.KeyStroke;
import javax.swing.ProgressMonitor;
import javax.swing.ProgressMonitorInputStream;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.border.Border;
import javax.swing.border.TitledBorder;

public class J2SEContext extends CommJ2SEContext implements IStatusListen{
    public static JPTrayIcon ti;
    private static JMenuItem transNewCertKey;
    private static CapNotify capNotify = new CapNotify();
    static{
    	CapManager.addListener(capNotify);
    }
    
	public J2SEContext() {
		SIPManager.setSIPContext(new J2SESIPContext(){

			@Override
			public Object buildSocket(int localPort, String targetServer, int targetPort){
				Object s = super.buildSocket(localPort, targetServer, targetPort);
				if(s == null){
					//要进行重连，不同于其它如Root，
					SIPManager.notifyRelineon(false);
				}
				return s;
			}
		});
		
		super.init(new ReceiveServer(), new J2SEUDPReceiveServer());

		if(IConstant.serverSide){
//			RelayManager.start(HttpUtil.getLocalIP(), SIPManager.relayPort, null);
			
			showTray();
			KeepaliveManager.keepalive.doNowAsynchronous();
			KeepaliveManager.keepalive.setEnable(true);
		}
		
	}
	
	public void interrupt(Thread thread){
		thread.interrupt();
	}
	
	public void exit(){
		ExitManager.exit();				
	}
	
	public void notifyShutdown(){
		//获得全部通讯，并通知下线。
		L.V = L.O ? false : LogManager.log("Shut down");
		if(IConstant.serverSide == false){
			ContextManager.shutDown();
		}else{
	    	DelayServer.getInstance().addDelayBiz(new AbstractDelayBiz(null){
				public void doBiz() {
					if(ti != null){
						SystemTray.getSystemTray().remove(ti);
						ti.exit();
						ti = null;
					}
	
					if(RelayManager.startMoveNewRelay(
							new RelayShutdownWatch() {
								public void extShutdown() {
									DelayServer.getInstance().shutDown();
								}
							})){
					}else{
						DelayServer.getInstance().shutDown();
					}
				}});
		}
    }
	
	private static long lastCanvasMainAction = 0;
	private static void doCanvasMain(String url){
		//TODO 删除时间过滤，由于版本普遍更新后，该过滤将失去作用
		//为了防服务器推送后,旧版本的客户端的请求再次到来,加时间过滤.
		final long currentTimeMillis = System.currentTimeMillis();
		if(currentTimeMillis - lastCanvasMainAction < 10000){
			return;
		}
		
		lastCanvasMainAction = currentTimeMillis;
		
		//检查UDP通道的可达性
		if(ContextManager.getContextInstance().isDoneUDPChannelCheck == false){
			L.V = L.O ? false : LogManager.log("Ready check UDP channel usable");
			if(ContextManager.getContextInstance().isBuildedUPDChannel){
				L.V = L.O ? false : LogManager.log("Auto Disable UDP Channel");
				//关闭不可通达的UDP
				ContextManager.getContextInstance().isBuildedUPDChannel = false;
			}else{
				L.V = L.O ? false : LogManager.log("UDP Channel is Disabled by NO_MSG_RECEIVE");
			}
			ContextManager.getContextInstance().isDoneUDPChannelCheck = true;
		}
		
//		L.V = L.O ? false : LogManager.log("Receive Req:" + url);
		DelayServer.getInstance().addDelayBiz(new AbstractDelayBiz(null) {
			@Override
			public void doBiz() {
				ServerUIUtil.responsor.onEvent(BackServer.EVENT_SYS_MOBILE_LOGIN);
			}
		});
		
		HCURLUtil.process(url, ContextManager.getContextInstance().getHCURLAction());
	}
	
	public void run() {
		super.run();
		
		ClientInitor.doNothing();
		
		EventCenter.addListener(new IEventHCListener(){
			public boolean action(final byte[] bs) {
//				if(SIPManager.isSameUUID(event.data_bs)){
					if(IConstant.serverSide){
						//客户端主动下线
						String token = Message.getMsgBody(bs, MsgBuilder.INDEX_MSG_DATA);
						if(token.equals(RootServerConnector.getHideToken())){
							ContextManager.getContextInstance().displayMessage(
									(String)ResourceUtil.get(IContext.INFO), 
									(String)ResourceUtil.get(9006), IContext.INFO, null, 0);
					
							notifyExitByMobi();
						}else{
							hc.core.L.V=hc.core.L.O?false:LogManager.log("Error Token at client shutdown");
						}
					}else{
						//TODO j2se客户机
					}
					return true;
//				}
//				return true;
			}

			public byte getEventTag() {
				return MsgBuilder.E_TAG_SHUT_DOWN_BETWEEN_CS;
			}});
		
		startAllServers();
		
//		KeepaliveManager.keepalive.setEnable(true);
//		KeepaliveManager.keepalive.doNowAsynchronous();
		
		if(IConstant.serverSide){
			//服务器端增加各种MobiUI应答逻辑
			
			EventCenter.addListener(new IEventHCListener(){
				public boolean action(final byte[] bs) {
					String jcip = Message.getMsgBody(bs, MsgBuilder.INDEX_MSG_DATA);
					JcipManager.responseFormSubmit(jcip);
					return true;
				}

				public byte getEventTag() {
					return MsgBuilder.E_JCIP_FORM_SUBMIT;
				}});

			EventCenter.addListener(new IEventHCListener(){
				public boolean action(final byte[] bs) {
					String formID = Message.getMsgBody(bs, MsgBuilder.INDEX_MSG_DATA);
					JcipManager.removeAutoResonseTimer(formID);
					return true;
				}

				public byte getEventTag() {
					return MsgBuilder.E_JCIP_FORM_EXIT;
				}});

			EventCenter.addListener(new IEventHCListener(){
				public boolean action(final byte[] bs) {
					String url = Message.getMsgBody(bs, MsgBuilder.INDEX_MSG_DATA);

					doCanvasMain(url);

					return true;
				}

				public byte getEventTag() {
					return MsgBuilder.E_CANVAS_MAIN;
				}});
			
			EventCenter.addListener(new IEventHCListener(){
				public boolean action(final byte[] bs) {
					if(ScreenServer.isServing() == false){
						DataClientAgent dss = new DataClientAgent();
						dss.setBytes(bs);
						ClientDesc.refreshClientInfo(dss);

						//如果手机版本过低，产生通知
						String pcReqMobiVer = (String)doExtBiz(BIZ_GET_REQ_MOBI_VER_FROM_PC, null);
						if(StringUtil.higer(pcReqMobiVer, ClientDesc.clientVer)){
							send(MsgBuilder.E_AFTER_CERT_STATUS, String.valueOf(IContext.BIZ_SERVER_AFTER_OLD_MOBI_VER_STATUS));
							LogManager.err("Min Reqire mobi ver : [" + pcReqMobiVer + "], Line In mobi ver : [" + ClientDesc.clientVer + "]");
							L.V = L.O ? false : LogManager.log("Cancel mobile login process");
							SIPManager.notifyRelineon(false);
							return true;
						}
						
						//服务器产生一个随机数，用CertKey和密码处理后待用，
						byte[] randomBS = new byte[MsgBuilder.UDP_BYTE_SIZE];
						CUtil.generateRandomKey(randomBS, MsgBuilder.INDEX_MSG_DATA, CUtil.TRANS_CERT_KEY_LEN);
						CUtil.resetCheck();
						CUtil.SERVER_READY_TO_CHECK = randomBS;
						
						byte[] randomEvent = ContextManager.cloneDatagram(randomBS);
						hc.core.L.V=hc.core.L.O?false:LogManager.log("Send random data to client for check CK and password");
//						try{
//							Thread.sleep(50);
//						}catch (Exception e) {
//						}
						send(MsgBuilder.E_RANDOM_FOR_CHECK_CK_PWD, randomEvent, CUtil.TRANS_CERT_KEY_LEN);

					}else{
						hc.core.L.V=hc.core.L.O?false:LogManager.log("In Serving, Skip other client desc");
					}
					return true;
				}

				public byte getEventTag() {
					return MsgBuilder.E_CLIENT_INFO;
				}});
		}
		
		if(IConstant.serverSide){
			//加载其它启动逻辑
			CaptureConfig cc = CaptureConfig.getInstance();
			if(cc.get(CaptureConfig.USE_VIDEO, IConstant.FALSE).equals(IConstant.TRUE)
					&& cc.getAutoRecord().equals(IConstant.TRUE)){
				CapStream.getInstance(false).startRecord(false);
			}
		}
	}
	
    static ImageIcon dl_certkey, disable_dl_certkey;
    Image hc_Enable, hc_Disable, hc_mobi;

    public void displayMessage(String caption, String text, int type, Object imageData, int timeOut){
    	MessageType mtype = null;
    	if(type == IContext.ERROR){
    		mtype = MessageType.ERROR;
    	}else if(type == IContext.INFO){
    		mtype = MessageType.INFO;
    	}else if(type == IContext.WARN){
    		mtype = MessageType.WARNING;
    	}else{
    		mtype = MessageType.INFO;
    	}
    	if(ti != null){
    		ti.displayMessage(caption, text, mtype);
    	}
    }
    
    public JPopupMenu popupTi = new JPopupMenu() ;//弹出菜单
	
    public static long lastCheckMS = System.currentTimeMillis();
    
    public static boolean checkPassword(boolean checkTime, String opName){
    	if((checkTime == false) || (System.currentTimeMillis() - lastCheckMS > 1000 * 60 * 3)){
    		PWDDialog pd = new PWDDialog();
    		
    		String pwd = App.getFromBASE64(PropertiesManager.getValue(PropertiesManager.p_password));
    		if(pd.pwd == null){
    			//取消操作
    			return false;
    		}
    		
    		if(pwd.equals(pd.pwd)){
    			refreshActionMS(true);
    			return true;
    		}
    		
    		if(opName != null){
    			L.V = L.O ? false : LogManager.log("Desktop Menu [" + opName + "] password error!");
    		}
    		Object[] options={(String)ResourceUtil.get(1010)};
    		JOptionPane.showOptionDialog(null, (String)ResourceUtil.get(1019), "HomeCenter", JOptionPane.DEFAULT_OPTION, JOptionPane.ERROR_MESSAGE, null, options, options[0]);
    		return false;
    	}else{
    		refreshActionMS(false);
    		return true;
    	}
    }

	public static void refreshActionMS(boolean isForce) {
		if(isForce || (System.currentTimeMillis() - lastCheckMS < 1000 * 60 * 3)){
			lastCheckMS = System.currentTimeMillis();
		}
	}
    
	private static final String _STARTER_PROP_FILE_NAME = "starter.properties";
    
	public void buildMenu(Locale locale){

		popupTi = new JPopupMenu();
    	
    	popupTi.applyComponentOrientation(ComponentOrientation.getOrientation(locale));
    	
        final JMenu hcMenu = new JMenu("HomeCenter");
        ImageIcon hcIcon = null;
        try{
        	hcIcon = new ImageIcon(ImageIO.read(ResourceUtil.getResource("hc/res/hc_22.png")));
        }catch (Exception e) {
			
		}
        try{
        	hcMenu.setIcon(hcIcon);
        }catch (Exception e) {
			
		}
        {
        	final String title = (String)ResourceUtil.get(9040);
			final JMenuItem option = new JMenuItem(title);
            ImageIcon optionIco = null;
            try{
            	optionIco = new ImageIcon(ImageIO.read(ResourceUtil.getResource("hc/res/option_22.png")));
            	option.setIcon(optionIco);
            }catch (Exception e) {
    		}
            option.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					SingleJFrame.showJFrame(ConfigPane.class);
				}
			});
            hcMenu.add(option);
            
			buildAutoUpgradMenuItem(hcMenu);

			if(TokenManager.isDonateToken() == false){
	        	final JMenuItem vip = new JMenuItem("VIP Register");
	        	try {
					vip.setIcon(new ImageIcon(ImageIO.read(ResourceUtil.getResource("hc/res/vip_22.png"))));
				} catch (IOException e4) {
				}
	        	vip.addActionListener(new ActionListener() {
					@Override
					public void actionPerformed(ActionEvent e) {
						App.showUnlock(false);
					}
				});
	        	hcMenu.add(vip);
        	}
        	
			//aboutus
			final JMenuItem aboutusItem = new JMenuItem("About HomeCenter");
			try{
				aboutusItem.setIcon(hcIcon);
			}catch (Exception e) {
				
			}
			aboutusItem.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					refreshActionMS(false);
					
					final JDialog dialog = new JDialog();
					dialog.setTitle("About HomeCenter");
					dialog.setIconImage(App.SYS_LOGO);

					final ActionListener disposeAction = new ActionListener() {
						@Override
						public void actionPerformed(ActionEvent e) {
							dialog.dispose();
						}
					};

					dialog.getRootPane().registerKeyboardAction(disposeAction, 
						KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0),
						JComponent.WHEN_IN_FOCUSED_WINDOW);

					JPanel panel = new JPanel();
					panel.setLayout(new GridLayout(0,1,3,3));
					try {
						JLabel icon = new JLabel(new ImageIcon(ImageIO.read(ResourceUtil.getResource("hc/res/hc_32.png"))));
						panel.add(icon);
						
					} catch (IOException e1) {
						e1.printStackTrace();
					}
					
					JLabel productName = new JLabel("HomeCenter - control desktop by mobile", null, JLabel.CENTER);
					if(App.VERIFY_ON){
						try {
							productName.setIcon(new ImageIcon(ImageIO.read(ResourceUtil.getResource("hc/res/verify_22.png"))));
						} catch (IOException e3) {
						}
					}
					
					panel.add(productName);
					
					JLabel ver = new JLabel("version : " + getVersion(), null, JLabel.CENTER);
					panel.add(ver);
					
					//今年的年数
					Calendar cal = Calendar.getInstance();
					int today_year = cal.get(Calendar.YEAR);
					String copyright = "Copyright © 2011 - " + today_year + " HomeCenter.MOBI";
					panel.add(new JLabel(copyright, null, JLabel.CENTER));
					
					panel.add(new JLabel("Mozilla Public License Version 1.1", null, JLabel.CENTER));
					
					JButton jbOK = null;
					try {
						jbOK = new JButton("O K", new ImageIcon(ImageIO.read(ImageSrc.OK_ICON)));
					} catch (IOException e1) {
						e1.printStackTrace();
					}
					JButton jbMail = null;
					try {
						Font defaultBtnFont = jbOK.getFont();
						jbMail = new JButton("help@homecenter.mobi", new ImageIcon(ImageIO.read(ResourceUtil.getResource("hc/res/email_22.png"))));
						HashMap<TextAttribute, Object> hm = new HashMap<TextAttribute, Object>(); 
						hm.put(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON);  // 定义是否有下划线 
						hm.put(TextAttribute.SIZE, defaultBtnFont.getSize());    // 定义字号 
						hm.put(TextAttribute.FAMILY, defaultBtnFont.getFamily());    // 定义字体名 
						Font font = new Font(hm);    // 生成字号为12，字体为宋体，字形带有下划线的字体 
						jbMail.setFont(font);
						jbMail.setBorderPainted(true);
						jbMail.setBorder(BorderFactory.createEmptyBorder());
					} catch (IOException e2) {
						e2.printStackTrace();
					}
					jbMail.addActionListener(new ActionListener() {
						@Override
						public void actionPerformed(ActionEvent e) {
				            Desktop desktop = Desktop.getDesktop();  
				            if (Desktop.isDesktopSupported() && desktop.isSupported(Desktop.Action.MAIL)) {  
				                try {
									desktop.mail(new java.net.URI("mailto:help@homecenter.mobi?subject=[HomeCenter.MOBI]%20Help%20:%20"));
								} catch (IOException e1) {
									e1.printStackTrace();
								} catch (URISyntaxException e1) {
									e1.printStackTrace();
								}  
				            }else{
				            	JOptionPane.showConfirmDialog(dialog, "Unable call operating system sending mail function!", "Error", JOptionPane.ERROR_MESSAGE);
				            }
	
						}
					});
					panel.add(jbMail);
	
					jbOK.addActionListener(disposeAction);
					panel.add(jbOK);
					
					
					dialog.add(panel);
					
					dialog.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
					jbOK.setFocusable(true);
					dialog.getRootPane().setDefaultButton(jbOK);
					jbOK.requestFocus();
					
					dialog.setResizable(false);
					dialog.setSize(400, 300);
					
					
					App.showCenter(dialog);
				}
			});
				
			hcMenu.add(aboutusItem);
			
        }
        popupTi.add(hcMenu);
        
        popupTi.addSeparator();
        //Tutorial
        final JMenuItem turoItem = new JMenuItem((String)ResourceUtil.get(9029));
        try{
        	turoItem.setIcon(new ImageIcon(ImageIO.read(ResourceUtil.getResource("hc/res/tuto_22.png"))));
        }catch (Exception e) {
			
		}
        turoItem.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				App.showTuto();
			}
		});
        popupTi.add(turoItem);
        
		//FAQ
		final JMenuItem faqItem = new JMenuItem((String)ResourceUtil.get(9013));//菜单项
        try {
        	faqItem.setIcon(new ImageIcon(ImageIO.read(ResourceUtil.getResource("hc/res/faq22.png"))));
		} catch (IOException e1) {
			e1.printStackTrace();
		}
        faqItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
            	refreshActionMS(false);
    			String targetURL;
				try {
					targetURL = HttpUtil.buildLangURL("pc/faq.htm", null);
	            	HttpUtil.browseLangURL(targetURL);
				} catch (UnsupportedEncodingException e1) {
					e1.printStackTrace();
				}

            }
        });
        popupTi.add(faqItem);
        
        popupTi.addSeparator();
        
        //选择语言
        final JMenu langSubItem = new JMenu("Language");
        try{
        	langSubItem.setIcon(new ImageIcon(ImageIO.read(ImageSrc.LANG_ICON)));
        }catch (Exception e) {
			
		}
        {
        	boolean isEn = PropertiesManager.isTrue(PropertiesManager.p_ForceEn);
        	
	        ButtonGroup group = new ButtonGroup();
	        final JRadioButtonMenuItem rbMenuItem = new JRadioButtonMenuItem("Auto Detect");
	        try {
				rbMenuItem.setIcon(new ImageIcon(ImageIO.read(ImageSrc.LANG_ICON)));
			} catch (IOException e2) {
			}
	        rbMenuItem.setSelected(!isEn);
	        group.add(rbMenuItem);
	        langSubItem.add(rbMenuItem);
	        rbMenuItem.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					refreshActionMS(false);
					
					UILang.setLocale(null);
					PropertiesManager.setValue(PropertiesManager.p_ForceEn, IConstant.FALSE);
					PropertiesManager.saveFile();
					buildMenu(UILang.getUsedLocale());
				}
			});
	
	        final JRadioButtonMenuItem enMenuItem = new JRadioButtonMenuItem("English");
	        try {
				enMenuItem.setIcon(new ImageIcon(ImageIO.read(ResourceUtil.getResource("hc/res/en_22.png"))));
			} catch (IOException e1) {
			}
	        enMenuItem.setSelected(isEn);
	        group.add(enMenuItem);
	        langSubItem.add(enMenuItem);
	        enMenuItem.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					refreshActionMS(false);
					
					final Locale locale = UILang.EN_LOCALE;
					UILang.setLocale(locale);
					PropertiesManager.setValue(PropertiesManager.p_ForceEn, IConstant.TRUE);
					PropertiesManager.saveFile();
					buildMenu(UILang.getUsedLocale());
				}
			});
        }
        popupTi.add(langSubItem);
        
		//登录改为密码
		final JMenuItem loginItem = new JMenuItem((String)ResourceUtil.get(1007));//菜单项
        try {
			loginItem.setIcon(new ImageIcon(ImageIO.read(ImageSrc.PASSWORD_ICON)));
		} catch (IOException e1) {
			e1.printStackTrace();
		}
        loginItem.addActionListener(new ActionListener() {
        	String opName = loginItem.getText();
            public void actionPerformed(ActionEvent e) {
            	if(checkPassword(false, opName)){
            		App.showInputPWDDialog(IConstant.uuid, "", "", false);
//            		new LoginDialog(loginItem);
            	}
            }
        });
        popupTi.add(loginItem);
        
        {
	        buildCaptureMenu();
        }
        
        popupTi.addSeparator();
        
        //浏览当天当前的日志
        final JMenuItem browseCurrLog = new JMenuItem((String)ResourceUtil.get(9002));
        ImageIcon currLog = null;
		try {
			currLog = new ImageIcon(ImageIO.read(ImageSrc.LOG_ICON));
		} catch (IOException e2) {
		}
		browseCurrLog.setIcon(currLog);
		ActionListener currLogAction = new ActionListener() {
			String opName = browseCurrLog.getText();
			LogViewer lv;
			public void actionPerformed(ActionEvent e) {
				if(checkPassword(true, opName)){
					if(lv == null || lv.isShowing() == false){
						String pwd = PropertiesManager.getValue(PropertiesManager.p_LogPassword1);
		
						byte[] pwdBS;
						try {
							pwdBS = App.getFromBASE64(pwd).getBytes(IConstant.UTF_8);
							lv = viewLog(ImageSrc.HC_LOG, pwdBS, (String)ResourceUtil.get(9002));
						} catch (UnsupportedEncodingException e1) {
							e1.printStackTrace();
						}
					}else{
						lv.setVisible(true);
					}
					
				}
			}
        };
		browseCurrLog.addActionListener(currLogAction);
        popupTi.add(browseCurrLog);
        
        //浏览前次的日志
        {
        	File file = new File(ImageSrc.HC_LOG_BAK);
            if(file.exists()){
		        final JMenuItem browseLogBak = new JMenuItem((String)ResourceUtil.get(9003));
		        ImageIcon currbakLog = null;
		        try {
					currbakLog = new ImageIcon(ImageIO.read(ImageSrc.LOG_BAK_ICON));
				} catch (IOException e2) {
				}
				browseLogBak.setIcon(currbakLog);
				browseLogBak.addActionListener(new ActionListener() {
					String opName = browseLogBak.getText();
					LogViewer lv;
					public void actionPerformed(ActionEvent e) {
						if(checkPassword(true, opName)){
							if(lv == null || lv.isShowing() == false){
								String pwd = PropertiesManager.getValue(PropertiesManager.p_LogPassword2);
								if(pwd != null){
									byte[] pwdBS;
									try {
										pwdBS = App.getFromBASE64(pwd).getBytes(IConstant.UTF_8);
										lv = viewLog(ImageSrc.HC_LOG_BAK, pwdBS, (String)ResourceUtil.get(9003));
									} catch (UnsupportedEncodingException e1) {
										e1.printStackTrace();
									}
								}else{
									runBrowser(ImageSrc.HC_LOG_BAK);
								}
							}else{
								lv.setVisible(true);
							}
						}
					}
		        });
		        popupTi.add(browseLogBak);
            }
        }
        
        popupTi.addSeparator();
        
        //生成新证书
        final JMenuItem buildNewCertKey = new JMenuItem((String)ResourceUtil.get(9001));
        BufferedImage newKey = null;
		try {
			newKey = ImageIO.read(ImageSrc.NEW_CERTKEY_ICON);
		} catch (IOException e2) {
		}
		buildNewCertKey.setToolTipText("new certification help to prevent hacker tries to login, encrypted transmission of data.");
        buildNewCertKey.setIcon(new ImageIcon(newKey));
        buildNewCertKey.addActionListener(new ActionListener() {
        	String opName = buildNewCertKey.getText();
			public void actionPerformed(ActionEvent e) {
				if(checkPassword(false, opName)){
					CUtil.generateRandomKey(CUtil.CertKey, 0, CUtil.CERT_KEY_LEN);
					IConstant.getInstance().setObject(IConstant.CertKey, CUtil.CertKey);
					
					if(ContextManager.cmStatus == ContextManager.STATUS_SERVER_SELF){
						//确保送达
						
						isTransedToMobileSize = false;
						
						transNewCertKey();
						
						ConditionWatcher.addWatcher(new IWatcher() {
							long curr = System.currentTimeMillis();
							@Override
							public boolean watch() {
								if(System.currentTimeMillis() - curr > 2000){
									BackServer.sendMessage((String) ResourceUtil.get(IContext.INFO), (String) ResourceUtil.get(9033), IContext.INFO, null, 0);
									return true;
								}
								return false;
							}
							
							@Override
							public void setPara(Object p) {
							}
							
							@Override
							public boolean isNotCancelable() {
								return false;
							}
							
							@Override
							public void cancel() {
							}
						});
						final JPanel panel = new JPanel();
						try {
							panel.add(new JLabel((String) ResourceUtil.get(9007), new ImageIcon(ImageIO.read(ImageSrc.OK_ICON)), SwingConstants.LEFT));
						} catch (IOException e2) {
						}
						App.showCenterPanel(panel, 0, 0, (String) ResourceUtil.get(IContext.INFO), false, null, new ActionListener() {
							@Override
							public void actionPerformed(ActionEvent e) {
							}
						}, null, null, false, false);
						ConditionWatcher.addWatcher(new IWatcher(){
							long curr = System.currentTimeMillis();
							
							@Override
							public boolean watch() {
								if(panel.isShowing()){
									return false;
								}
								
								if(System.currentTimeMillis() - curr > 6000){
									if(isTransedToMobileSize){
										doAfterMobileReceivedCert();
									}else{
										doAfterCertIsNotTransed();
									}
								}

								
								return true;
							}

							@Override
							public void setPara(Object p) {
							}

							@Override
							public void cancel() {
							}

							@Override
							public boolean isNotCancelable() {
								return false;
							}});
						return ;
						//END 在线传送证书
					}else{
						doAfterCertIsNotTransed();
					}
				}
			}
        });
        popupTi.add(buildNewCertKey);
        
        //传输新证书开关
		transNewCertKey = new JMenuItem("");//菜单项
		transNewCertKey.setToolTipText("<html>If 'Transmit:on', when mobile login with invalid certification, " +
				"new certification will be transmited and store to mobile;" +
				"<BR>if 'Transmit:off', only mobile with the right certification and password can login.</html>");
		initEnableTransNewCert();
		if(isEnableTransNewCertNow()){
			transNewCertKey.setIcon(dl_certkey);
			transNewCertKey.setText((String)ResourceUtil.get(1021));
		}else{
			transNewCertKey.setIcon(disable_dl_certkey);
			transNewCertKey.setText((String)ResourceUtil.get(1020));			
		}
		if(PropertiesManager.isTrue(PropertiesManager.p_NewCertIsNotTransed) 
            			&& (isEnableTransNewCertNow())){
			transNewCertKey.setEnabled(false);
		}
		
		transNewCertKey.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
            	refreshActionMS(false);
//            	if(checkPassword(false)){
//            	if(PropertiesManager.isTrue(PropertiesManager.p_NewCertIsNotTransed) 
//            			&& (isEnableTransNewCertNow())){
//					JPanel panel = new JPanel();
//					try {
//						panel.add(new JLabel("<html><body>The new certification is never transmited"
//								+ "<BR><BR>No mobile phone got it now." +
//								"<BR>If 'Transmit Certification : off', " +
//								"no mobile can login this server with older certification.<BR>" +
//								"In order to make the mobile get it, please keep 'Transmit Certification : on'" +
//								"</body></html>", new ImageIcon(ImageIO.read(ImageSrc.CANCEL_ICON)), SwingConstants.LEFT));
//					} catch (IOException e2) {
//					}
//            		App.showCenterPanel(panel, 0, 0, (String) ResourceUtil.get(IContext.INFO), false, 
//            				new JButton((String)ResourceUtil.get(1018), new ImageIcon(ImageSrc.CANCEL_ICON)), null);
//            	}else{
	            	flipTransable(!isEnableTransNewCertNow());
//            	}
//            	}
            }
        });
        popupTi.add(transNewCertKey);
                
        popupTi.addSeparator();
        
        {
//    		if((RootConfig.getInstance().isTrue(RootConfig.p_ShowDesinger))){
//    	        if(RootConfig.getInstance().isTrue(RootConfig.p_ShowDesingerToAll) 
//    	        		|| TokenManager.isDonateToken()){
//    		        popupTi.addSeparator();
        	{
    		        final JMenuItem designer = new JMenuItem((String)ResourceUtil.get(9034));//菜单项
    		        ImageIcon designIco = null;
    		        
    				//检查是否有新版本
    				final String lastSampleVer = PropertiesManager.getValue(PropertiesManager.p_LastSampleVer, "1.0");
    				if(StringUtil.higer(RootConfig.getInstance().getProperty(RootConfig.p_Sample_Ver), lastSampleVer)){
    					try {
        					designIco = new ImageIcon(ImageIO.read(ResourceUtil.getResource("hc/res/designernew_22.png")));
        				} catch (IOException e2) {
        					e2.printStackTrace();
        				}
    				}else{
        				try {
        					designIco = new ImageIcon(ImageIO.read(ResourceUtil.getResource("hc/res/designer_22.png")));
        				} catch (IOException e2) {
        					e2.printStackTrace();
        				}    					
    				}

	            	designer.setIcon(designIco);
    	            designer.addActionListener(new ActionListener() {
    	                public void actionPerformed(ActionEvent e) {
    	                	refreshActionMS(false);
    	                	
            				String jrubyjar = PropertiesManager.getValue(PropertiesManager.p_jrubyJarFile);
            				if(jrubyjar == null){
            					final Properties thirdlibs = ResourceUtil.loadThirdLibs();
            					if(thirdlibs == null){
            						return;
            					}

//								int out = JOptionPane.showConfirmDialog(null, "Script engine need JRuby lib (jruby.org, about 18M), install it now?", "install JRuby online?", 
//            							JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
//            					if(out == JOptionPane.OK_OPTION){
            						IBiz agreeBiz = new IBiz() {
										@Override
										public void start() {
				    	                	new Thread(){
				    	                		public void run(){
													ProgressMonitorInputStream pmis = null;
													FileOutputStream fos = null;
													try{
														java.security.MessageDigest md = java.security.MessageDigest.getInstance( "MD5" );
														File rubyjar = new File(J2SEContext.jrubyjarname);
														if(rubyjar.exists()){
															rubyjar.delete();
														}
														fos = new FileOutputStream(rubyjar);
														final byte[] bs = new byte[1024 * 5];
														URL url = new URL(thirdlibs.getProperty("jruby.url"));
														int total = url.openConnection().getContentLength();
														if(total <= 0){
															total = 20000000;
														}
														pmis = new ProgressMonitorInputStream(null, "download JRuby lib...", url.openStream());
														
														ProgressMonitor progressMonitor = pmis.getProgressMonitor();
														progressMonitor.setMillisToDecideToPopup(1000);
														progressMonitor.setMillisToPopup(1000);
														progressMonitor.setMaximum(total);
														
														int readed = 0;
														int blockSize = 0;
														final long startMS = System.currentTimeMillis();
														long costMS = 0;
														while ((blockSize = pmis.read(bs)) != -1) {
															fos.write(bs, 0, blockSize);
															md.update(bs, 0, blockSize);
															
															readed += blockSize;
															
															float process = (float) readed / total * 100;// 算出百分比
															costMS = System.currentTimeMillis() - startMS;
															long leftSeconds = (costMS * total / readed - costMS) / 1000;
															progressMonitor.setNote("" + ((int)process) + "%, " + leftSeconds + " seconds");// 显示在进度条上
												      	}
														
														String dnmd5 = ResourceUtil.toMD5(md.digest());
														if(dnmd5.equals(thirdlibs.getProperty("jruby.md5"))){
															PropertiesManager.setValue(PropertiesManager.p_jrubyJarFile, J2SEContext.jrubyjarname);	
															PropertiesManager.setValue(PropertiesManager.p_jrubyJarVer, thirdlibs.getProperty("jruby.ver"));
															PropertiesManager.saveFile();
															
															runDesigner();
															
															final JPanel panelxx = new JPanel();
															try {
																panelxx.setLayout(new BorderLayout());
																panelxx.add(new JLabel("Success setup JRuby!", new ImageIcon(ImageIO.read(ImageSrc.OK_ICON)), SwingConstants.LEFT), BorderLayout.NORTH);
																
																JLabel next = new JLabel("<html>" +
																		"<body style=\"width:400\"><BR>" +
																		"<STRONG>Mobile UI Designer</STRONG><BR>It is tool to config and program to connect with " +
																		"home smart devices, such as DVD, TV, Camera, Air conditioner. " +
																		"<BR><BR>More than contorl and access PC desktop screen.<BR><BR>" +
																		"<STRONG>How to using Mobile UI Designer</STRONG>" +
																		"<img src='http://homecenter.mobi/images/tip.png' width='16' height='16'></img>" +
																		"<BR>" +
																		"1. click 'Sample' button to download sample project online,<BR>" +
																		"2. click 'Save' button,<BR>" +
																		"3. click 'Deploy' button to apply the sample UI,<BR>" +
																		"4. connect mobile to PC by Wi-Fi or 3G,<BR>" +
																		"5. click menu item on mobile to call function, such as control TV, DVD...<BR>" +
																		"6. to test JRuby script, click 'Test Script' button.<BR>" +
																		"7. share the project to friends, just click 'Share to' button.<BR>" +
																		"</html>");
																panelxx.add(next, BorderLayout.CENTER);
															} catch (IOException e2) {
															}
															App.showCenterPanel(panelxx, 0, 0, "JRuby OK and Next", false, null, new ActionListener() {
																@Override
																public void actionPerformed(ActionEvent e) {
																}
															}, null, null, false, true);
														}else{
															JOptionPane.showMessageDialog(null, "The jruby lib is invailid of MD5, please try after few minutes!", 
																	"MD5 error", JOptionPane.ERROR_MESSAGE);
															return;
														}
													}catch (Exception e) {
														RootServerConnector.notifyLineOffType("lof=JRubyErr");
														JOptionPane.showMessageDialog(null, "Error : " + e.toString(), "Error", JOptionPane.ERROR_MESSAGE);
													}finally{
														try{
															pmis.close();
														}catch (Exception e) {
															
														}
														try{
															fos.close();
														}catch (Exception e) {
															
														}
													}
				    	                		}
				    	                	}.start();
										}
										
										@Override
										public void setMap(HashMap map) {
										}
										
									};
									App.showAgreeLicense("JRuby License (third lib, NOT HomeCenter)", thirdlibs.getProperty("jruby.license"), agreeBiz, false);
//            					}//安装前提示
            				}else{
            					runDesigner();
            				}
    	                }
    	            });
    	            popupTi.add(designer);
        	}
//    	        }
//            }

        	
			final JMenuItem mapItem = new JMenuItem((String)ResourceUtil.get(9035));//菜单项
        	try {
        		mapItem.setIcon(new ImageIcon(ImageIO.read(
						ResourceUtil.getResource("hc/res/map_22.png"))));
			} catch (IOException e1) {
			}
        	mapItem.addActionListener(new ActionListener() {
	            public void actionPerformed(ActionEvent e) {
	            	refreshActionMS(false);
	            	
	            	try{
	            		KeyComperPanel.showKeyComperPanel();
	            	}catch (Exception ee) {
						JOptionPane.showConfirmDialog(null, "Cant load Key", 
								"Error", JOptionPane.CLOSED_OPTION, JOptionPane.ERROR_MESSAGE);
					}
	            }
	        });
	        
	        popupTi.add(mapItem);
        }

        
        if(App.VERIFY_ON == false){
	        popupTi.addSeparator();
	        final JMenuItem verifyItem = new JMenuItem("Verify me");
	        try {
	        	verifyItem.setIcon(new ImageIcon(ImageIO.read(
	        			ResourceUtil.getResource("hc/res/verify_22.png"))));
			} catch (IOException e1) {
				e1.printStackTrace();
			}
	        
	        verifyItem.addActionListener(new ActionListener(){
				@Override
				public void actionPerformed(ActionEvent e) {
					JPanel panel = new JPanel();
					panel.add(new JLabel("<html><body style='width:400'><STRONG>Verify Me</STRONG><BR><BR>" +
							"The newer starter(loader) provides powerful verify mechanism, " +
							"which verify each upgraded lib (downloaded by Auto Upgrade) with X509. " +
							"more effective way to protect your system from network risk.<BR><BR>" +
							"1. shutdown this HomeCenter App Server<BR>" +
							"2. click 'O K' goto http://homecenter.mobi<BR>" +
							"3. download and unzip the newer HomeCenter App Server<BR>" +
							"4. run HomeCenter App Server, new starter would 'Verify Me'.<BR>" +
							"</body></html>"));
					App.showCenterPanel(panel, 0, 0, "Go to download", false, null, new ActionListener() {
						@Override
						public void actionPerformed(ActionEvent e) {
							HttpUtil.browse("http://homecenter.mobi/?verifyme");
						}
					}, null, null, false, false);
				}});
	        
	        popupTi.add(verifyItem);
        }

        popupTi.addSeparator();
        
        //退出
        final JMenuItem exitItem = new JMenuItem(
        		(String)ResourceUtil.get(IContext.EXIT) + "   (" + IConstant.uuid + ")");//菜单项
        try {
			exitItem.setIcon(new ImageIcon(ImageIO.read(ImageSrc.EXIT_ICON)));
		} catch (IOException e1) {
			e1.printStackTrace();
		}
        exitItem.addActionListener(new ActionListener() {
        	String opName = exitItem.getText();
            public void actionPerformed(ActionEvent e) {
            	if(checkPassword(true, opName)){
            		if(ContextManager.cmStatus == ContextManager.STATUS_SERVER_SELF){
            			ContextManager.getContextInstance().send(MsgBuilder.E_TAG_SHUT_DOWN_BETWEEN_CS, RootServerConnector.getHideToken());
            			
            			//在模拟环境中，由于UDP的后滞性，E_TAG_SHUT_DOWN_BETWEEN_CS基本不被送出
            		}
            		
            		RootServerConnector.notifyLineOffType(RootServerConnector.LOFF_ServerReq_STR);
            		//以上逻辑不能置于notifyShutdown中，因为这些方法有可能被其它外部事件，如手机下线，中继下线触发。
            		
            		ContextManager.notifyShutdown();
            	}
            }
        });
        popupTi.add(exitItem);
        
        SystemTray tray = SystemTray.getSystemTray();
		// 切换皮肤时，会导致异常，所以不复用对象。
		if (ti != null) {
			tray.remove(ti);
		}
		try {
			ContextManager.statusListen = this;
			ti = new JPTrayIcon((ti != null ? ti.getImage() : hc_Disable),
					(String) ResourceUtil.get(UILang.PRODUCT_NAME), popupTi);

			ti.addActionListener(currLogAction);

		} catch (Exception e1) {
			e1.printStackTrace();
		}// 图标，标题，右键弹出菜单

		try {
			tray.add(ti);// 在系统托盘区中增加图标
		} catch (Exception e) {
			System.err.println(e);
		}
    }

	private void buildCaptureMenu() {
		popupTi.addSeparator();

		final JMenu cameraMenu = new JMenu((String)ResourceUtil.get(9048));
		ImageIcon cameraIcon = null;
		try{
			cameraIcon = new ImageIcon(ImageSrc.BUILD_SMALL_ICON);
		}catch (Exception e) {
		}

		//camera
		final JMenuItem cameraItem = new JMenuItem((String)ResourceUtil.get(9040), cameraIcon);
		try{
			cameraMenu.setIcon(new ImageIcon(ImageIO.read(ResourceUtil.getResource("hc/res/camera_22.png"))));
		}catch (Exception e) {
		}
		cameraMenu.add(cameraItem);
		
		Class checkJMFClass = null;
		try{
			checkJMFClass = Class.forName("javax.media.CaptureDeviceManager");
		}catch (Exception e) {
		}
		if(checkJMFClass == null){
			cameraItem.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					CapManager.installJMF();
				}
			});
			
			popupTi.add(cameraMenu);
			//未安装JMF
			return ;
		}else{
			cameraItem.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					SingleJFrame.showJFrame(CapControlFrame.class);
				}
			});
		}
		final JMenuItem cameraStart = new JMenuItem();
		final JMenuItem cameraStop = new JMenuItem();
		cameraStart.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				CapPreviewPane.doStart();
			}
		});
		cameraStop.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				CapPreviewPane.doStop();
			}
		});
		cameraMenu.add(cameraStart);
		
		cameraStop.setText((String)ResourceUtil.get(9052));
		try{
			cameraStop.setIcon(new ImageIcon(ImageIO.read(ResourceUtil.getResource("hc/res/stop_22.png"))));
		}catch (Exception e) {
		}
		cameraMenu.add(cameraStop);

		capNotify.setMenuItem(cameraMenu, cameraStart, cameraStop);
		int capEnable = CapStream.CAP_DISABLE;
		try{
			capEnable = CaptureConfig.isCapEnable()?CapStream.CAP_ENABLE:CapStream.CAP_DISABLE;
		    capNotify.notifyNewMsg(String.valueOf(capEnable));
		    final CapStream instance = CapStream.getInstance(false);
		    if(instance != null){
		    	capNotify.notifyNewMsg(String.valueOf(instance.getCapStatus()));
		    }
		}catch (Error e) {
			//有可能未安装，没有相关类。
		}
		
		popupTi.add(cameraMenu);
	}

	/**
     * 暂停使用，因为中继端可能升级，导致不可预知的问题
     * @param hcMenu
     */
	private void buildAutoUpgradMenuItem(final JMenu hcMenu) {
		final JCheckBoxMenuItem upgradeItem = new JCheckBoxMenuItem((String)ResourceUtil.get(9031));
		upgradeItem.setSelected(!PropertiesManager.isTrue(PropertiesManager.p_isNotAutoUpgrade));
		try{
			upgradeItem.setIcon(new ImageIcon(ImageIO.read(ResourceUtil.getResource("hc/res/upgrade_22.png"))));
		}catch (Exception e) {
		}
		upgradeItem.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				final boolean isAutoAfterClick = upgradeItem.isSelected();
				if(isAutoAfterClick == false){
					int ok = JOptionPane.showConfirmDialog(null, 
							"Important :" +
							"\n" +
							"\n1. If upgrade mobile side, please keep this App server to be the newest." +
							"\n2. If upgrade App Server, please keep mobile side to be the newest." +
							"\n3. In insecure networks, please do NOT upgrade." +
							"\n4. If exception, try keep both to be the newest, maybe the relay server was upgraded.", 
						"Before Disable Auto Upgrade...", 
						JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE);
					if(ok == JOptionPane.OK_OPTION){
						
					}else{
						upgradeItem.setSelected(!isAutoAfterClick);
						return;
					}
				}
				final String MAX_VER = "9999999";//注意与Starter.NO_UPGRADE_VER保持同步
				
				//更新到Properties文件中
				Properties start = new Properties();
				try{
					start.load(new FileInputStream(_STARTER_PROP_FILE_NAME));
				}catch (Exception ex) {
					JOptionPane.showConfirmDialog(null, "Unable open file starter.properties.", "Error", JOptionPane.ERROR_MESSAGE);
					upgradeItem.setSelected(!isAutoAfterClick);					
					return;
				}
				if(isAutoAfterClick){
					start.setProperty("ver", 
							PropertiesManager.getValue(PropertiesManager.p_LasterAutoUpgradeVer));
				}else{
					PropertiesManager.setValue(PropertiesManager.p_LasterAutoUpgradeVer,
							start.getProperty("ver"));
					start.setProperty("ver", MAX_VER);
				}
				try {
					start.store(new FileOutputStream(_STARTER_PROP_FILE_NAME), "");
				} catch (Exception e1) {
					JOptionPane.showConfirmDialog(null, "Unable write file " + _STARTER_PROP_FILE_NAME + ".", "Error", JOptionPane.ERROR_MESSAGE);
					upgradeItem.setSelected(!isAutoAfterClick);
					return;
				}

//					upgradeItem.setSelected(isOldAuto);
				PropertiesManager.setValue(PropertiesManager.p_isNotAutoUpgrade, 
						(isAutoAfterClick == false)?IConstant.TRUE:IConstant.FALSE);
				PropertiesManager.saveFile();
				
				if(isAutoAfterClick){
					ImageIcon icon = null;
					try {
						icon = new ImageIcon(ImageIO.read(ImageSrc.OK_ICON));
					} catch (IOException e1) {
						e1.printStackTrace();
					}
					JOptionPane.showMessageDialog(null, 
							"Upgrading will check and execute when HomeCenter App Server restart." +
							"\n\n" +
							"Note : There is NO effect to mobile side.", 
							"Success Enable Auto Upgrade!", JOptionPane.INFORMATION_MESSAGE, 
							icon);
				}
			}
		});
		hcMenu.add(upgradeItem);
	}
    
	public void showTray() {
		try {
			disable_dl_certkey = new ImageIcon(ImageIO.read(ImageSrc.DISABLE_DL_CERTKEY_ICON));
			dl_certkey = new ImageIcon(ImageIO.read(ImageSrc.DL_CERTKEY_ICON));
			hc_Enable = ImageIO.read(ResourceUtil.getResource("hc/res/hc_48.jpg"));
			hc_Disable = ImageIO.read(ResourceUtil.getResource("hc/res/hc_dis_48.jpg"));
			hc_mobi = ImageIO.read(ResourceUtil.getResource("hc/res/hc_mobi_48.jpg"));
		} catch (IOException e1) {
			e1.printStackTrace();
		}

		buildMenu(UILang.getUsedLocale());
        
        Runtime.getRuntime().addShutdownHook(new Thread(){
        	public void run(){
        		//因为系统调用System.exit时，会激活此处。
        		//L.V = L.O ? false : LogManager.log("User Power Off");
        		ContextManager.notifyShutdown();
        	}
        });
        
        if(IConstant.serverSide){
        	String msg = (String)ResourceUtil.get(9009);
			displayMessage((String)ResourceUtil.get(IContext.INFO), msg, 
        			IContext.INFO, null, 0);
        	ti.setToolTip(msg);
        }
	}
	
	public static String[][] splitFileAndVer(String files, boolean isTempMode){
		String[] fs = files.split(";");
		
		int size = fs.length;
		String[][] out = new String[size][2];
		
		for (int i = 0; i < size; i++) {
			String[] tmp = fs[i].split(":");
			if(tmp.length < 2){
				return null;
			}
			out[i][0] = tmp[0];
			out[i][1] = tmp[1];
		}
		
		return out;
	}
	
	public static LogViewer viewLog(String fileName, byte[] pwdBS, String title) { 
		LogManager.flush();
		
        try {  
            File file = new File(fileName);
            if(file.exists() == false){
            	ContextManager.getContextInstance().displayMessage((String) ResourceUtil.get(IContext.ERROR), 
						(String) ResourceUtil.get(9004), IContext.ERROR, null, 0);
            	return null;
            }
            
            FileInputStream in = new FileInputStream(file);
            Object desc = file.toString();
            
            InputStreamReader reader = new InputStreamReader(
            		ServerCUtil.decodeStream((InputStream)in, pwdBS), IConstant.UTF_8);  
            return LogViewer.loadFile(reader, desc, title);
        } catch (Exception ex) {  
            ex.printStackTrace();  
            JOptionPane.showMessageDialog(null, ex.toString());
        }  
        return null;
    }  
	
	public static void runBrowser(String fileName) {  
        try {  
            File file = new File(fileName);
            if(file.exists() == false){
            	ContextManager.getContextInstance().displayMessage((String) ResourceUtil.get(IContext.ERROR), 
						(String) ResourceUtil.get(9004), IContext.ERROR, null, 0);
            	return;
            }
            Desktop desktop = Desktop.getDesktop();  
            if (desktop.isDesktopSupported() && desktop.isSupported(Desktop.Action.OPEN)) {  
                desktop.open(file);  
            }else{
            	ContextManager.getContextInstance().displayMessage((String) ResourceUtil.get(IContext.ERROR), 
						(String) ResourceUtil.get(9005), IContext.ERROR, null, 0);
            }
        } catch (IOException ex) {  
            ex.printStackTrace();  
        }  
    }  
	
	public Object getSysImg() {
		return App.SYS_LOGO;
	}

	public boolean isSoundOnMode() {
		//TODO isSoundOff
		return false;
	}
	
//	public final void send(byte type_request, InetAddress address, int port) {
//		DatagramPacket p = (DatagramPacket)dpCacher.getFree();
//		
//		byte[] bs = p.getData();
//		
//		Message.setSendUUID(bs, selfUUID, selfUUID.length);
//		
//		bs[MsgBuilder.INDEX_CTRL_TAG] = type_request;
//		bs[MsgBuilder.INDEX_PACKET_SPLIT] = MsgBuilder.DATA_PACKET_NOT_SPLIT;
//		p.setLength(MsgBuilder.MIN_LEN_MSG);
////		p.setData(bs, 0, MsgBuilder.MIN_LEN_MSG);
//		
//		p.setAddress(address);
//		p.setPort(port);
//		
//		sServer.pushIn(p);
//	}
	
//	/**
//	 * 该逻辑被切换中继，j2se客户端，服务器进入接入等调用
//	 * 注意：各调用环境的条件状态
//	 */
//	public final void setTargetPeer(String ip, String port, Object datagram) throws Exception {
//		if(datagram == null){
//			int status = ContextManager.cmStatus;
//			
//			try {
//				if(status == ContextManager.STATUS_SERVER_SELF || status == ContextManager.STATUS_CLIENT_SELF){
//					//Relay切换到另一个Relay
//				}else{
//					J2SESIPContext.endPunchHoleProcess();
//				}
//				hc.core.L.V=hc.core.L.O?false:LogManager.log("setTargetPeer, IP:" + ip + ":" + port);
//				TargetPeer tp = new TargetPeer();
//				tp.clientInet = InetAddress.getByName(ip);
//				tp.clientPort = Integer.parseInt(port);
//				KeepaliveManager.setClient(tp);
//			} catch (Exception e) {
//				e.printStackTrace();
//			}
//		}else{
//			DatagramPacket packet = (DatagramPacket)datagram;
//			try {
//				packet.setAddress(InetAddress.getByName(ip));
//			} catch (UnknownHostException e) {
//				e.printStackTrace();
//			}
//			packet.setPort(Integer.parseInt(port));
//		}
//	}

	public Object doExtBiz(short bizNo, Object newParam) {
		if(bizNo == IContext.BIZ_LOAD_SERVER_CONFIG){
			if(IConstant.serverSide){
				ServerConfig sc = new ServerConfig();
//				if(SIPManager.isRelayServerNATType(NatHcTimer.LocalNATType)){
//					//具备中继型的服务器，对客户机进行最优发现，上限不超过均值
//					sc.setTryMaxMTU(MsgBuilder.UDP_DEFAULT_BYTE_SIZE);
//				}else if(SIPManager.isOnRelay()){
//					//依赖于中继的服务器，上限不能高于均值
//					sc.setTryMaxMTU(MsgBuilder.UDP_DEFAULT_BYTE_SIZE);					
//				}else{
//					//TODO 从用户配置中，获得尝试的最大传送块
//					sc.setTryMaxMTU(MsgBuilder.UDP_DEFAULT_BYTE_SIZE);
//				}
//
//				//TODO 从用户配置中，获得是否要求进行最优发现，缺省为0
//				sc.setMTU(1448);//MTU设置为0，表示通知客户端，要进行最优发现
//				sc.setTryMaxMTU(Integer.parseInt(
//						RootConfig.getInstance().getProperty(RootConfig.p_MaxUDPSize)));//仅在MTU设置为0下，最优化时，尝试的上限(含)
				
				sc.setServerTokenXXX("");
				ServerConfig.setInstance(sc);
				return sc;
			}else{
				return null;
			}
//		}else if(bizNo == IContext.BIZ_IS_ON_SERVICE){
//			if(IConstant.serverSide){
//				KeepaliveManager.keepalive.setEnable(true);
//			}
		}else if(bizNo == IContext.BIZ_UPLOAD_LINE_ON){
//			String hostAddress = SIPManager.LocalNATIPAddress;
//
//			if(hostAddress.equals(SIPManager.getExternalUPnPIPAddress())){
//				hc.core.L.V=hc.core.L.O?false:LogManager.log("UPnP external IP == Public IP");
//				SIPManager.LocalNATPort = SIPManager.getExternalUPnPPort();
//				SIPManager.LocalNATType = EnumNAT.OPEN_INTERNET;
//			}
			
//			if(IConstant.serverSide && SIPManager.isRelayFullOpenMode(SIPManager.LocalNATType)){
//				RelayManager.notifyIsRelayServer();
//			}

//			ti.putTip(JPTrayIcon.NAT_DESC, EnumNAT.getNatDesc(UDPChannel.nattype));
//			ti.putTip(JPTrayIcon.PUBLIC_IP, hostAddress + ":" + String.valueOf(UDPChannel.publicPort));
			
			String out = RootServerConnector.lineOn(
					IConstant.uuid, KeepaliveManager.homeWirelessIpPort.ip, 
					KeepaliveManager.homeWirelessIpPort.port, 0, 1, 
					KeepaliveManager.relayServerUPnPIP, KeepaliveManager.relayServerUPnPPort,
					SIPManager.relayIpPort.ip, SIPManager.relayIpPort.port, TokenManager.getToken(), 
					!isEnableTransNewCertNow(), RootServerConnector.getHideToken());
			
			if(out == null){
				LogManager.err("unable to connect root server");
				SIPManager.notifyRelineon(true);
				String[] ret = {"false"};
				return ret;
			}else if(out.equals("e")){
				String msg = "Same ID is using now, try another ID!";
				LogManager.err(msg);
				
				JOptionPane.showMessageDialog(null,
					msg, (String) ResourceUtil
							.get(IContext.ERROR), JOptionPane.ERROR_MESSAGE);
				
				notifyShutdown();
				String[] ret = {"false"};
				return ret;
			}else if(out.equals("d")){
				RootConfig.getInstance().setProperty(RootConfig.p_Color_On_Relay, "5");
				RootConfig.getInstance().setProperty(RootConfig.p_MS_On_Relay, 50);
			}
			
			SingleMessageNotify.closeDialog(SingleMessageNotify.TYPE_ERROR_CONNECTION);
			setTrayEnable(true);
			
//			本地无线信息，不需在日志中出现。
//				hc.core.L.V=hc.core.L.O?false:LogManager.log("Success line on " 
//						+ ServerUIUtil.replaceIPWithHC(KeepaliveManager.homeWirelessIpPort.ip) + ", port : " 
//						+ KeepaliveManager.homeWirelessIpPort.port + " for client connection");
			
			//上传上线信息
			if(SIPManager.relayIpPort.port > 0){	
				hc.core.L.V=hc.core.L.O?false:LogManager.log("Success line on " 
						+ ServerUIUtil.replaceIPWithHC(SIPManager.relayIpPort.ip)  + ", port : " 
						+ SIPManager.relayIpPort.port + " for client connection");
			}
			
			return null;
		}else if(bizNo == IContext.BIZ_AFTER_HOLE){
			if(IConstant.serverSide){
//				KeepaliveManager.keepalive.setEnable(true);
//				hc.core.L.V=hc.core.L.O?false:LogManager.log("Active Keepalive Watcher");
				
				//开启断线侦测
//				KeepaliveManager.ConnBuilderWatcher.setEnable(true);
				
				//关闭连接异常侦测
				//注意：与keepAliveWatcher.setEnable状态互斥
//				NatHcTimer.timerPunchHole.setEnable(false);
				
				//服务器端
				ServerConfig sc = (ServerConfig)ContextManager.getContextInstance().doExtBiz(IContext.BIZ_LOAD_SERVER_CONFIG, null);
				final byte[] serverconfigBS = new byte[MsgBuilder.UDP_BYTE_SIZE];
				DataServerConfig dsc = new DataServerConfig();
				dsc.setBytes(serverconfigBS);
				sc.writeTo(dsc);
				ContextManager.getContextInstance().send(
						MsgBuilder.E_TRANS_SERVER_CONFIG, serverconfigBS, dsc.getLength());
				L.V = L.O ? false : LogManager.log("Transed Server Config");
				
				//传输完Server_Config后，进入MTU设置或最优发现侦听
//				if(ServerConfig.getInstance().getMTU() != 0){
//					SIPManager.notifyUDPSize(ServerConfig.getInstance().getMTU());
//				}else{
//					//初始化MTU于服务器
////					MsgBuilder.refreshUDPByteLen(MsgBuilder.UDP_DEFAULT_BYTE_SIZE);
//					
//					//加载MTU优化事件侦听器
//					if(ServerMTUTimer != null){
//						ServerRecMaxMTU = 0;
//						ServerMTUTimer.resetTimerCount();
//						ServerMTUTimer.setEnable(true);
//					}else{
//						ServerMTUTimer = new HCTimer("MTU Best", 4000, true){
//							public void doBiz() {
//								if(ServerRecMaxMTU > 0){
//									SIPManager.notifyUDPSize(ServerRecMaxMTU);
//									setEnable(false);
//									
//									//没有加2，由客户端以补充存储两位空间
//									ContextManager.getContextInstance().send(MsgBuilder.E_FIND_UDP_MTU_SIZE_BACK, String.valueOf(ServerRecMaxMTU));
//
//									ServerRecMaxMTU = 0;
//								}else{
//									hc.core.L.V=hc.core.L.O?false:LogManager.log("No receive MTU UDP");
//								}
//							}};
//						EventCenter.addListener(new IEventHCListener(){
//							final DataMTUTest dmt = new DataMTUTest();
//							public boolean action(final byte[] bs) {
//								byte[] bs = event.data_bs;
//								dmt.setBytes(bs);
//								if(dmt.passData()){
//									int tmpMaxMTU = dmt.getLength() + MsgBuilder.INDEX_MSG_DATA;
//									if(tmpMaxMTU > ServerRecMaxMTU){
//										ServerRecMaxMTU = tmpMaxMTU;
//										if(ServerMTUTimer != null){
//											ServerMTUTimer.resetTimerCount();
//										}
//									}
//								}
//								return true;
//							}
//
//							public byte getEventTag() {
//								return MsgBuilder.E_FIND_UDP_MTU_SIZE;
//							}});
//					}
//				}

				//等待，让ServerConfig先于后面的包到达目标

//				DelayServer.getInstance().addDelayBiz(new AbstractDelayBiz(null) {
//					@Override
//					public void doBiz() {
//						try{
//							Thread.sleep(1000);
//						}catch (Exception e) {
//							
//						}
//					}
//				});
				//并将该随机数发送给客户机，客户机用同法处理后回转给服务器
				//服务器据此判断客户机的CertKey和密码状态				

//				ContextManager.setStatus(ContextManager.STATUS_READY_FOR_CLIENT);
			}
			
			return null;
		}
		
//		if(bizNo == IContext.BIZ_OPEN_REQ_BUILD_CONN_LISTEN){
//			EventCenter.addListener(new IEventHCListener(){
//				public boolean action(final byte[] bs) {
//					if(ContextManager.isNotWorkingStatus()){
//						send(MsgBuilder.E_TAG_REQUEST_BUILD_CONNECTION);
//						hc.core.L.V=hc.core.L.O?false:LogManager.log("Successful connect to the target peer");
//						ContextManager.setStatus(ContextManager.STATUS_READY_FOR_CLIENT);
//						if(IConstant.serverSide){
//							//将askForService移出，因为有可能密码验证不通过
//							NatHcTimer.LISTENER_FROM_HTTP.setEnable(false);
//						}
//					}
//					return true;
//				}
//	
//				public byte getEventTag() {
//					return MsgBuilder.E_TAG_REQUEST_BUILD_CONNECTION;
//				}});
//			return null;
//		}
		if(bizNo == IContext.BIZ_CHANGE_RELAY){
			String[] ips = (String[])newParam;
			RootServerConnector.changeRelay(IConstant.uuid, ips[0], ips[1], TokenManager.getToken());
			return null;
		}else if(bizNo == IContext.BIZ_GET_TOKEN){
			return TokenManager.getTokenBS();
		}else if(bizNo == IContext.BIZ_SET_TRAY_ENABLE){
			if(newParam instanceof Boolean){
				boolean b = (Boolean)newParam;
				setTrayEnable(b);
			}
			return null;
		}
		
		if(IConstant.serverSide){
			if(bizNo == IContext.BIZ_SERVER_AFTER_CERTKEY_AND_PWD_PASS){
				doAfterCertKeyAndPwdPass();
			}else if(bizNo == IContext.BIZ_SERVER_AFTER_CERTKEY_ERROR){
				doAfterCertKeyError();
				RootServerConnector.notifyLineOffType(RootServerConnector.LOFF_CertErr_STR);
			}else if(bizNo == IContext.BIZ_SERVER_AFTER_PWD_ERROR){
				doAfterPwdError();
				RootServerConnector.notifyLineOffType(RootServerConnector.LOFF_pwdErr_STR);
			}
		}else{
			if(bizNo == IContext.BIZ_SERVER_AFTER_CERTKEY_AND_PWD_PASS){
			}else if(bizNo == IContext.BIZ_SERVER_AFTER_CERTKEY_ERROR){
			}else if(bizNo == IContext.BIZ_SERVER_AFTER_PWD_ERROR){
			}else if(bizNo == IContext.BIZ_SERVER_AFTER_SERVICE_IS_FULL){
				
			}else if(bizNo == IContext.BIZ_SERVER_AFTER_UNKNOW_STATUS){
				
			}
		}
		if(bizNo == IContext.BIZ_VERSION_MID_OR_PC){
			return getVersion();
		}else if(bizNo == IContext.BIZ_GET_REQ_MOBI_VER_FROM_PC){
			return "5.55";
		}
		return null;
	}

	private void doAfterCertKeyAndPwdPass() {
		if(ScreenServer.askForService()){
			ServerCUtil.transOneTimeCertKey();
			
			hc.core.L.V=hc.core.L.O?false:LogManager.log("Pass Certification Key and password");
			
			//由于会传送OneTimeKey，所以不需要下步
			//instance.send(MsgBuilder.E_AFTER_CERT_STATUS, String.valueOf(IContext.BIZ_SERVER_AFTER_CERTKEY_AND_PWD_PASS));

			try{
				Thread.sleep(1000);
			}catch (Exception e) {
			}
			
			ContextManager.setStatus(ContextManager.STATUS_SERVER_SELF);
			
			//由原来的客户端请求,改为服务器推送
			doCanvasMain("menu://root");
			
			//关闭以防被再次接入
			DelayServer.getInstance().addDelayBiz(new AbstractDelayBiz(null) {
				@Override
				public void doBiz() {
					RootServerConnector.delLineInfo(TokenManager.getToken(), true);
				}
			});
//			final TargetPeer target = KeepaliveManager.target;

			String msg = (String)ResourceUtil.get(9012);
			displayMessage((String) ResourceUtil.get(IContext.INFO), msg, 
					IContext.INFO, null, 0);
			ti.setToolTip(msg);
			ti.setImage(hc_mobi);

		}else{
			hc.core.L.V=hc.core.L.O?false:LogManager.log("Service is full, error for client connection");
			send(MsgBuilder.E_AFTER_CERT_STATUS, String.valueOf(IContext.BIZ_SERVER_AFTER_SERVICE_IS_FULL));
			
			SIPManager.notifyRelineon(true);
		}
	}

	private static void doAfterPwdError() {
		hc.core.L.V=hc.core.L.O?false:LogManager.log("Send Error password status to client");
		ContextManager.getContextInstance().send(MsgBuilder.E_AFTER_CERT_STATUS, String.valueOf(IContext.BIZ_SERVER_AFTER_PWD_ERROR));
//		try{
//			Thread.sleep(1000);
//		}catch (Exception e) {
//			
//		}
		SIPManager.notifyRelineon(true);
	}

	private static void doAfterCertKeyError() {
		if(isEnableTransNewCertNow()){
			//传输证书
			transNewCertKey();
//			try{
//				//增加时间，确保transOneTimeCertKey后于NewCertKey
//				Thread.sleep(300);
//			}catch (Exception e) {
//				
//			}
			hc.core.L.V=hc.core.L.O?false:LogManager.log(RootServerConnector.unObfuscate("rtnapsro teCtrK yet  olceitn."));
			
			if(PropertiesManager.isTrue(PropertiesManager.p_NewCertIsNotTransed)){
				PropertiesManager.setValue(PropertiesManager.p_NewCertIsNotTransed, IConstant.FALSE);
				PropertiesManager.saveFile();

				transNewCertKey.setEnabled(true);
				
				new Thread(){
					public void run(){
						JPanel tipPanle = new JPanel(new GridLayout(1, 3));
						tipPanle.setBorder(new TitledBorder(((String)ResourceUtil.get(1021)) + "?"));
						tipPanle.add(new JLabel(dl_certkey));
						try {
							tipPanle.add(new JLabel(new ImageIcon(ImageIO.read(ImageSrc.MOVE_TO_ICON))));
						} catch (IOException e1) {
							e1.printStackTrace();
						}
						tipPanle.add(new JLabel(disable_dl_certkey));
	
						App.showCenterPanel(tipPanle, 0, 0, "HomeCenter", true, null, new ActionListener() {
							@Override
							public void actionPerformed(ActionEvent e) {
								if(isEnableTransNewCertNow()){
									flipTransable(false);
								}
							}
						}, null, null, false, false);
					}
				}.start();
			}
			
		}else{
			hc.core.L.V=hc.core.L.O?false:LogManager.log(RootServerConnector.unObfuscate("eSdni vniail deCtrficitaoi ntstasut  olceitn"));
			ContextManager.getContextInstance().send(MsgBuilder.E_AFTER_CERT_STATUS, String.valueOf(IContext.BIZ_SERVER_AFTER_CERTKEY_ERROR));
			SingleMessageNotify.showOnce(SingleMessageNotify.TYPE_ERROR_CERT, 
					"Mobile login with ERROR CertKey<BR><BR>If you created new certification, please enable transmit, " +
					"<BR>your mobile will get new certification.", "Error Certification", 1000 * 60,
					App.getSysIcon(App.SYS_ERROR_ICON));
//			LogManager.errToLog("Mobile login with ERROR CertKey");
			SIPManager.notifyRelineon(true);
		}
	}

	private static void transNewCertKey() {
		ServerCUtil.transCertKey(CUtil.CertKey, MsgBuilder.E_TRANS_NEW_CERT_KEY);
	}
	
	private static boolean enableTransCertKey;
	
	public static void enableTransCertKey(boolean enable){
		if(enable){
			PropertiesManager.setValue(PropertiesManager.p_EnableTransNewCertKeyNow, IConstant.TRUE);
		}else{
			PropertiesManager.setValue(PropertiesManager.p_EnableTransNewCertKeyNow, IConstant.FALSE);
		}
		PropertiesManager.saveFile();
		enableTransCertKey = enable;

		RootServerConnector.refreshRootAlive(TokenManager.getToken(),
				!isEnableTransNewCertNow(), RootServerConnector.getHideToken());
	}
	
	public static boolean isEnableTransNewCertNow(){
		return enableTransCertKey;
	}
	
	public static void initEnableTransNewCert(){
		String out = PropertiesManager.getValue(PropertiesManager.p_EnableTransNewCertKeyNow);
		if(out == null || out.equals(IConstant.TRUE)){
			enableTransCertKey = true;
		}else{
			enableTransCertKey = false;
		}
	}

	public Object getProperty(Object propertyID) {
		return PropertiesManager.getValue((String)propertyID);
	}

//	public void copyDatagramAddress(Object from, Object to) {
//		DatagramPacket dpTo = (DatagramPacket)to;
//		DatagramPacket dpFrom = (DatagramPacket)from;
//		
//		dpTo.setSocketAddress(dpFrom.getSocketAddress());
//	}

	final IHCURLAction urlAction = new J2SEServerURLAction();
	
	public static final String jrubyjarname = "jruby.jar";
	public IHCURLAction getHCURLAction() {
		return urlAction;
	}

	@Override
	public void notify(short statusFrom, short statusTo) {
		if(statusTo == ContextManager.STATUS_LINEOFF){
			
			if(statusFrom == ContextManager.STATUS_SERVER_SELF){
				ScreenServer.emptyScreen();
				ServerUIUtil.responsor.onEvent(BackServer.EVENT_SYS_MOBILE_LOGOUT);
			}
		}
		
		if(statusTo == ContextManager.STATUS_NEED_NAT){
			setTrayEnable(false);
			if(ti != null){
				ti.setDefaultToolTip();
			}
		}else if(statusFrom == ContextManager.STATUS_NEED_NAT){
		}

		if(statusTo == ContextManager.STATUS_READY_TO_LINE_ON){
			//由于被其它ID占用，所以此处setTrayEnable(true）移到成功上传之后
//			setTrayEnable(true);
		}

		if(statusTo == ContextManager.STATUS_READY_MTU){
			//直联或中继初始接入，但未进入验证参数传送
			KeepaliveManager.ConnBuilderWatcher.resetTimerCount();
			KeepaliveManager.ConnBuilderWatcher.setEnable(true);				
		}
		
		if(statusTo == ContextManager.STATUS_SERVER_SELF){
//			L.V = L.O ? false : LogManager.log("set setIntervalMS to " + KeepaliveManager.KEEPALIVE_MS);
			KeepaliveManager.keepalive.setIntervalMS(KeepaliveManager.KEEPALIVE_MS);
		}
	}

	private void setTrayEnable(boolean b){
		L.V = L.O ? false : LogManager.log("TrayEnable:" + b);
		if(b){
			if(ti != null){
				ti.setImage(hc_Enable);
			}
		}else{
			if(ti != null){
				if(ti.getImage() == hc_Enable){
					displayMessage((String) ResourceUtil.get(IContext.INFO), 
							(String)ResourceUtil.get(9009), 
							IContext.INFO, null, 0);
				}
				ti.setImage(hc_Disable);
			}
		}
	}

	public static String getVersion() {
		try{
			Properties start = new Properties();
			start.load(new FileInputStream(_STARTER_PROP_FILE_NAME));
			String[][] jars = splitFileAndVer(start.getProperty("JarFiles"), false);
			for (int i = 0; i < jars.length; i++) {
				String[] tmp = jars[i];
				if(tmp[0].equals("hc.jar")){
					//增加版本信息
					return tmp[1];
				}
			}
		}catch (Exception ee) {
			
		}
		return "";
	}

	private void runDesigner() {
		try{
			Class design = Class.forName(RootServerConnector.unObfuscate("chs.reev.riud.segi.neDisngre"));
			SingleJFrame.showJFrame(design);
		}catch (Exception ee) {
			JOptionPane.showConfirmDialog(null, "Cant load Designer", 
					"Error", JOptionPane.CLOSED_OPTION, JOptionPane.ERROR_MESSAGE);
		}
	}
	
	public static boolean isTransedToMobileSize = false;
	
	private void doAfterCertIsNotTransed() {
		PropertiesManager.setValue(PropertiesManager.p_NewCertIsNotTransed, IConstant.TRUE);
		PropertiesManager.saveFile();
		
		if(!isEnableTransNewCertNow()){
			flipTransable(!isEnableTransNewCertNow());
		}
		transNewCertKey.setEnabled(false);
		
		JPanel panel = new JPanel();
		try {
			panel.add(new JLabel("<html><body>" + (String) ResourceUtil.get(9007)
					+ "<BR><BR>Know more<BR>1. keep 'Transmit Certification : on' " +
					"<BR>2. mobile phone download it when login with old wrong certification" +
					"<BR>3. keep 'Transmit Certification : off', to defend harmful attacks" +
					"</body></html>", new ImageIcon(ImageIO.read(ImageSrc.OK_ICON)), SwingConstants.LEFT));
		} catch (IOException e2) {
		}
		App.showCenterPanel(panel, 0, 0, (String) ResourceUtil.get(IContext.INFO), 
				false, null, null, null, null, false, false);
	}

	private void doAfterMobileReceivedCert() {
		JPanel nextpanel = new JPanel();
		try {
			nextpanel.add(new JLabel((String) ResourceUtil.get(9032), new ImageIcon(ImageIO.read(ImageSrc.OK_ICON)), SwingConstants.LEFT));
		} catch (IOException e2) {
		}
		App.showCenterPanel(nextpanel, 0, 0, (String) ResourceUtil.get(IContext.INFO), false, null, new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
			}
		}, null, null, false, false);
	}

	public static void notifyExitByMobi() {
		hc.core.L.V=hc.core.L.O?false:LogManager.log("Client/Relay request lineoff!");

		RootServerConnector.notifyLineOffType(RootServerConnector.LOFF_MobReqExitToPC_STR);

		SIPManager.notifyRelineon(true);
	}

	public static void appendTitleJRubyVer(JFrame frame) {
		String ver = PropertiesManager.getValue(PropertiesManager.p_jrubyJarVer);
		if(ver != null){
			frame.setTitle(frame.getTitle() + " - [JRuby:" + ver + "]");
		}
	}

	public static void flipTransable(final boolean isEnable) {
		enableTransCertKey(isEnable);
		if(isEnable){
			transNewCertKey.setIcon(dl_certkey);
			transNewCertKey.setText((String)ResourceUtil.get(1021));	
		}else{
			transNewCertKey.setIcon(disable_dl_certkey);
			transNewCertKey.setText((String)ResourceUtil.get(1020));			
		}
		
		JPanel tipPanle = new JPanel(new GridLayout(1, 3));
		
		tipPanle.add(new JLabel(isEnable?disable_dl_certkey:dl_certkey));
		try {
			tipPanle.add(new JLabel(new ImageIcon(ImageIO.read(ImageSrc.MOVE_TO_G_ICON))));
		} catch (IOException e1) {
			e1.printStackTrace();
		}
		tipPanle.add(new JLabel(isEnable?dl_certkey:disable_dl_certkey));

		App.showCenterPanel(tipPanle, 0, 0, (isEnable?(String)ResourceUtil.get(1020):(String)ResourceUtil.get(1021)));
	}

}

class PWDDialog extends JDialog {
	JPanel jPanel2 = new JPanel();
	JPanel jPanel3 = new JPanel();
	Border border1;
	TitledBorder titledBorder1;
	GridBagLayout gridBagLayout2 = new GridBagLayout();
	GridBagLayout gridBagLayout3 = new GridBagLayout();
	JLabel jlPassword = new JLabel();
	JButton jbOK = null;
	JButton jbExit = null;
	JPasswordField jPasswordField1 = new JPasswordField(15);// 20个字符宽度

	public PWDDialog() {
		setModal(true);
		
		try {
			init();

			setVisible(true);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	private void init() throws Exception {

		setTitle("HomeCenter");
		this.setIconImage(App.SYS_LOGO);//new File("hc/res/hc_16.png")
		
		java.awt.event.ActionListener exitActionListener = new java.awt.event.ActionListener() {
			public void actionPerformed(ActionEvent e) {
				jbExit_actionPerformed(e);
			}
		};

		this.getRootPane().registerKeyboardAction(exitActionListener,
	            KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0),
	            JComponent.WHEN_IN_FOCUSED_WINDOW);
		
		//必须有此行代码，作为窗口右上的关闭响应
//		setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
		setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
		this.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				jbExit_actionPerformed(null);
			}

		});
		
		jbOK = new JButton("", new ImageIcon(ImageSrc.OK_ICON));
		jbExit = new JButton("", new ImageIcon(ImageSrc.CANCEL_ICON));

		// new LineBorder(Color.LIGHT_GRAY, 1, true)
		titledBorder1 = new TitledBorder((String)ResourceUtil.get(1007));// BorderFactory.createEtchedBorder()
		
		JPanel root = new JPanel();
		
		App.addBorderGap(this.getContentPane(), root);
		
		root.setLayout(gridBagLayout2);
		jPanel2.setLayout(gridBagLayout3);
		jPanel2.setBorder(titledBorder1);

		jbOK.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(ActionEvent e) {
//				System.out.println(e);
				if(e.getSource() == jbOK){ 
					jbOK_actionPerformed(e);
				}
			}
		});

		jlPassword.setHorizontalAlignment(SwingConstants.RIGHT);
		jlPassword.setIcon(new ImageIcon(ImageSrc.PASSWORD_ICON));	

		jbOK.setNextFocusableComponent(jbExit);
		jbOK.setSelected(true);
		jbOK.setText((String) ResourceUtil.get(IContext.OK));

		jbExit.setText((String) ResourceUtil.get(1018));
		jbExit.addActionListener(exitActionListener);

		jPasswordField1.setEchoChar('*');
		jPasswordField1.setHorizontalAlignment(SwingUtilities.RIGHT);
		jPasswordField1.enableInputMethods(true);
		
		root.add(
				jPanel2,
				new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0,
						GridBagConstraints.CENTER, GridBagConstraints.BOTH,
						new Insets(0, 0, 0, 0), 0, 0));

		final Insets insets = new Insets(5, 5, 5, 5);
		jPanel2.add(jlPassword, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0,
				GridBagConstraints.LINE_START, GridBagConstraints.NONE, insets, 0, 0));
		jPanel2.add(jPasswordField1, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0,
				GridBagConstraints.LINE_END, GridBagConstraints.NONE, insets, 0, 0));
		root.add(
				jPanel3,
				new GridBagConstraints(0, 2, 1, 1, 1.0, 1.0,
						GridBagConstraints.CENTER, GridBagConstraints.BOTH,
						new Insets(0, 0, 0, 0), 0, 0));
		jPanel3.add(jbOK, null);
		jPanel3.add(jbExit, null);

		this.getRootPane().setDefaultButton(jbOK);

		pack();
		// int width = 400, height = 270;
		int width = getWidth(), height = getHeight();
		setSize(width, height);

		int w = (Toolkit.getDefaultToolkit().getScreenSize().width - width) / 2;
		int h = (Toolkit.getDefaultToolkit().getScreenSize().height - height) / 2;
		setLocation(w, h);
		
	}
	
	void jbOK_actionPerformed(ActionEvent e) {
		pwd = jPasswordField1.getText();
		endDialog();
	}

	void jbExit_actionPerformed(ActionEvent e) {
		endDialog();
	}

	private void endDialog() {
		super.dispose();
	}
	
	public String pwd;
}
class CapNotify implements IMsgNotifier {
	ImageIcon readyIcon, recordingCameraIcon, recordIcon, pauseIcon, resumeIcon;
	private final String CMD_RECORD = (String)ResourceUtil.get(9049);
	private final String CMD_PAUSE = (String)ResourceUtil.get(9050);
	private final String CMD_RESUME = (String)ResourceUtil.get(9051);

	@Override
	public void notifyNewMsg(String msg) {
		final int currStatus = Integer.parseInt(msg);
		
		if(readyIcon == null){
			try{
		    	readyIcon = new ImageIcon(ImageIO.read(ResourceUtil.getResource("hc/res/camera_22.png")));
		    }catch (Exception e) {
			}
			try{
				recordingCameraIcon = new ImageIcon(ImageIO.read(ResourceUtil.getResource("hc/res/camera_on_22.png")));
		    }catch (Exception e) {
				
			}
			try{
				recordIcon = new ImageIcon(ImageIO.read(ResourceUtil.getResource("hc/res/record_22.png")));
				pauseIcon = new ImageIcon(ImageIO.read(ResourceUtil.getResource("hc/res/pause_22.png")));
				resumeIcon = new ImageIcon(ImageIO.read(ResourceUtil.getResource("hc/res/play_22.png")));
			}catch (Exception e) {
			}
		}
		if(currStatus == CapStream.CAP_RECORDING
				|| currStatus == CapStream.CAP_PAUSEING){
			capItem.setIcon(recordingCameraIcon);
		}else{
			capItem.setIcon(readyIcon);
		}
		
		if(currStatus == CapStream.CAP_ENABLE){
			startItem.setVisible(true);
		} else {
			CapStream instance = null;
			try{
				instance = CapStream.getInstance(false);
			}catch (Error e) {
			}
			if((currStatus == CapStream.CAP_DISABLE)
					&& (instance == null 
						|| instance.getCapStatus() == CapStream.CAP_NO_WORKING)){
				startItem.setVisible(false);
				stopItem.setVisible(false);
			}
		}
		
		if(currStatus == CapStream.CAP_NO_WORKING){
			startItem.setText(CMD_RECORD);
			startItem.setIcon(recordIcon);
			stopItem.setVisible(false);
			if(CaptureConfig.isCapEnable() == false){
				startItem.setVisible(false);
			}
		}else if(currStatus == CapStream.CAP_RECORDING){
			startItem.setText(CMD_PAUSE);
			startItem.setIcon(pauseIcon);
			stopItem.setVisible(true);
		}else if(currStatus == CapStream.CAP_PAUSEING){
			startItem.setText(CMD_RESUME);
			startItem.setIcon(resumeIcon);
		}
	}

	@Override
	public String getNextMsg() {
		return null;
	}
	private JMenuItem startItem, stopItem;
	private JMenu capItem;
	
	public void setMenuItem(JMenu item, JMenuItem startItem, JMenuItem stopItem){
		this.capItem = item;
		this.startItem = startItem;
		this.stopItem = stopItem;
	}
	
}